package com.tea.modules.java8.thread.synchronize;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 主要演示synchronized关键字的使用场景:  <br>
 * 1. 修饰代码块  <br>
 * 2. 修饰非静态方法 <br>
 * 3. 修饰静态方法   <br>
 * 4. 修饰对象      <br>
 *
 * @author jaymin
 * @since 2022/2/27 23:01
 */
@Slf4j
public class SynchronizedDemo {

    public static void main(String[] args) {
//        testSyncCode();
        testSyncClass();
    }

    private static void testSyncClass() {
        SynchronizedDemo synchronizedDemoA = new SynchronizedDemo();
        SynchronizedDemo synchronizedDemoB = new SynchronizedDemo();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(synchronizedDemoA::syncClass);
        executorService.execute(synchronizedDemoA::syncClass);
        executorService.execute(synchronizedDemoB::syncClass);
    }

    /**
     * 这里，i的值会依次打印，第一个获取时间片的代码执行完方法后，第二个继续执行<br>
     * 但是只能作用于同一个对象，不同的对象不受到同步约束 <br>
     * 所以在A对象内，执行2个方法，是同步执行。而AB是交替执行，互不影响 <br>
     */
    private static void testSyncCode() {
        SynchronizedDemo synchronizedDemoA = new SynchronizedDemo();
        SynchronizedDemo synchronizedDemoB = new SynchronizedDemo();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(synchronizedDemoA::syncCode);
        executorService.execute(synchronizedDemoA::syncCode);
        executorService.execute(synchronizedDemoB::syncCode);
    }

    /**
     * 修饰代码块
     */
    public void syncCode() {
        synchronized (this) {
            for (int i = 0; i < 10; i++) {
                log.info("current i value :{}", i);
            }
        }
    }

    /**
     * 修饰方法 <br>
     * 如果是子类调用父类的synchronized方法，那么不生效 <br>
     * 因为synchronized不属于方法声明的一部分
     */
    public synchronized void syncNormalMethod() {
        for (int i = 0; i < 10; i++) {
            log.info("current i value :{}", i);
        }
    }

    /**
     * 修饰静态方法 <br>
     * 会锁住所有跟这个类相关的对象
     */
    public static synchronized void syncStaticMethod() {
        for (int i = 0; i < 10; i++) {
            log.info("current i value :{}", i);
        }
    }


    /**
     * 修饰类
     * 会锁住所有跟这个类相关的对象
     */
    public void syncClass() {
        synchronized (SynchronizedDemo.class) {
            for (int i = 0; i < 10; i++) {
                log.info("current i value :{}", i);
            }
        }
    }


}
